// VParam.cpp: implementation of the CVParam class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "VParam.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CVParam::CVParam(const VARIANT vParam)
{
	if (vParam.vt == VT_BSTR)
	{
		CString strParams = vParam.bstrVal;
		Init(strParams);
	}
}

CVParam::CVParam(LPCTSTR pszParam, TCHAR s /* = _T */)
{
	Init(pszParam, s);
}

void CVParam::Init(LPCTSTR pszParam, TCHAR s /* = _T */)
{
	CString strParams = pszParam;
	int iParamLen = strParams.GetLength ();
	if (iParamLen < 1)
		return;
	
	if (strParams [iParamLen - 1] != s)
	{
		strParams += s;
	}
	
	for (int iFrom = 0; iFrom < strParams.GetLength (); )
	{
		int iEnd = strParams.Find (s, iFrom);
		if (iEnd < 0)
			break;
		
		CString strParam = strParams.Mid (iFrom, iEnd - iFrom);
		m_params.Add(strParam);
		iFrom = iEnd + 1;
	}
}

CVParam::~CVParam()
{

}

BOOL CVParam::SimpleScanf(LPCTSTR lpszText, LPCTSTR lpszFormat, ...)
{
	va_list pData;
	va_start(pData, lpszFormat);

	ASSERT(lpszText != NULL);
	ASSERT(lpszFormat != NULL);

	ASSERT(*lpszFormat == '%');
	lpszFormat++;        // skip '%'

	BOOL bLong = FALSE;
	BOOL bShort = FALSE;
	if (*lpszFormat == 'l')
	{
		bLong = TRUE;
		lpszFormat++;
	}
	else if (*lpszFormat == 's')
	{
		bShort = TRUE;
		lpszFormat++;
	}

	ASSERT(*lpszFormat == 'd' || *lpszFormat == 'u');
	ASSERT(lpszFormat[1] == '\0');

	while (*lpszText == ' ' || *lpszText == '\t')
		lpszText++;
	TCHAR chFirst = lpszText[0];
	long l, l2;
	if (*lpszFormat == 'd')
	{
		// signed
		l = _tcstol(lpszText, (LPTSTR*)&lpszText, 10);
		l2 = (int)l;
	}
	else
	{
		// unsigned
		if (*lpszText == '-')
			return FALSE;
		l = (long)_tcstoul(lpszText, (LPTSTR*)&lpszText, 10);
		l2 = (unsigned int)l;
	}
	
	if (l == 0 && chFirst != '0')
		return FALSE;   // could not convert

	while (*lpszText == ' ' || *lpszText == '\t')
		lpszText++;
	if (*lpszText != '\0')
		return FALSE;   // not terminated properly

	if (bShort)
	{
		if ((short)l != l)
			return FALSE;   // too big for short
		*va_arg(pData, short*) = (short)l;
	}
	else
	{
		ASSERT(sizeof(long) == sizeof(int));
		ASSERT(l == l2);
		*va_arg(pData, long*) = l;
	}

	// all ok
	va_end(pData);

	return TRUE;
}

BOOL CVParam::SimpleFloatParse(LPCTSTR lpszText, double& d)
{
	ASSERT(lpszText != NULL);
	while (*lpszText == ' ' || *lpszText == '\t')
		lpszText++;
	
	TCHAR chFirst = lpszText[0];
	d = _tcstod(lpszText, (LPTSTR*)&lpszText);
	if (d == 0.0 && chFirst != '0')
		return FALSE;   // could not convert
	while (*lpszText == ' ' || *lpszText == '\t')
		lpszText++;
	
	if (*lpszText != '\0')
		return FALSE;   // not terminated properly
	
	return TRUE;
}

BOOL CVParam::GetP(int i, int& iVal)
{
	if (i < m_params.GetSize())
		return SimpleScanf(m_params[i], _T("%d"), &iVal);

	return FALSE;
}

BOOL CVParam::GetP(int i, UINT& uiVal)
{
	if (i < m_params.GetSize())
		return SimpleScanf(m_params[i], _T("%u"), &uiVal);

	return FALSE;
}

BOOL CVParam::GetP(int i, long& lVal)
{
	if (i < m_params.GetSize())
		return SimpleScanf(m_params[i], _T("%ld"), &lVal);

	return FALSE;
}

BOOL CVParam::GetP(int i, double& dblVal)
{
	if (i < m_params.GetSize())
		return SimpleFloatParse(m_params[i], dblVal);

	return FALSE;
}

BOOL CVParam::GetP(int i, CString& strVal)
{
	if (i < m_params.GetSize())
	{
		strVal = m_params[i];
		return TRUE;
	}

	return FALSE;
}